<?php

// function isUndefined($var) {
//     return array_key_exists($var, get_defined_vars());
// }

//将 $input 数组的所有 $keys（逗号分隔） 的值取出
//$index为true，则用原 key 做关联，否则取出来为索引数组
//$default：如果 $input 中没有 某个key，则用这个默认值来替代（为null则跳过）
function array_keys_value(array $input, $keys = null, $index = false, $default = null): array
{
    $result = [];
    $keys   = explode(',', $keys);

    foreach ($keys as $v) {
        if (array_key_exists($v, $input)) {
            if ($index)
                $result[$v] = $input[$v];
            else
                $result[] = $input[$v];
        } else if ($default !== null) {
            if ($index)
                $result[$v] = $default;
            else
                $result[] = $default;
        }

    }
    return $result;
}

/**
 * 返回数组（二维数组）中指定多列
 *
 * @param Array       $input       需要取出数组列的多维数组
 * @param String|null $column_keys 要取出的列名，逗号分隔，如不传则返回所有列
 * @param String|null $index_key   作为返回数组的索引的列
 *
 * @return Array
 */
function array_columns(array $input, string $column_keys = null, string $index_key = null): array
{
    $result = array();

    $keys = isset($column_keys) ? explode(',', $column_keys) : array();

    if ($input) {
        foreach ($input as $k => $v) {

            // 指定返回列
            if ($keys) {
                $tmp = array();
                foreach ($keys as $key) {
                    $tmp[$key] = $v[$key];
                }
            } else {
                $tmp = $v;
            }

            // 指定索引列
            if (isset($index_key)) {
                $result[$v[$index_key]] = $tmp;
            } else {
                $result[] = $tmp;
            }
        }
    }

    return $result;
}

//获取客户真实IP
function get_real_ip()
{
    $ip = FALSE;
    //客户端IP 或 NONE
    if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }
    //多重代理服务器下的客户端真实IP地址（可能伪造）,如果没有使用代理，此字段为空
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(", ", $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) {
            array_unshift($ips, $ip);
            $ip = FALSE;
        }
        for ($i = 0; $i < count($ips); $i++) {
//            if (!eregi("^(10│172.16│192.168).", $ips[$i])) {
//                $ip = $ips[$i];
//                break;
//            }
            if (!preg_match("/^(10|172\.16|192\.168)\./i", $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    //客户端IP 或 (最后一个)代理服务器 IP
    return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}

//get_client_ip(0)返回ip    get_client_ip(1)返回ipv4的数字地址
function get_client_ip($type = 0, $adv = false)
{
    $type = $type ? 1 : 0;
    static $ip = NULL;
    if ($ip !== NULL)
        return $ip[$type];
    if ($adv) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown', $arr);
            if (false !== $pos) unset($arr[$pos]);
            $ip = trim($arr[0]);
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
    } elseif (isset($_SERVER['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $long = sprintf("%u", ip2long($ip));
    $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}

//返回当前的毫秒时间戳
function msectime(): float
{
    list($msec, $sec) = explode(' ', microtime());
    return (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
}

function ret_value($code = 0, $msg = "", $data = null, $httpCode = 200, $header = [], $others = []): \think\response\Json
{
    if (is_null($httpCode))
        $httpCode = 200;
    if (is_null($header))
        $header = [];

    $retData = array_merge($others, ["code" => $code, "msg" => $msg, "data" => $data]);
    return json($retData)->code($httpCode)->header($header);
}

// 应用公共文件
if (!function_exists('opt_photo')) {
    //图库选择
    function opt_photo($val): string
    {
        return '<button class="pear-btn pear-btn-primary pear-btn-sm" style="margin:4px 5px;vertical-align:top;" id="' . $val . '" type="button">图库选择</button>
       <script>
       layui.use(["jquery"],function() {
        let $ = layui.jquery;
        //弹出窗设置 自己设置弹出百分比
        function screen() {
            if (typeof width !== "number" || width === 0) {
            width = $(window).width() * 0.8;
            }
            if (typeof height !== "number" || height === 0) {
            height = $(window).height() - 20;
            }
            return [width + "px", height + "px"];
        }
        $("#' . $val . '").on("click", function () {
            layer.open({
                type: 2,
                maxmin: true,
                title: "图库选择",
                shade: 0.1,
                area: screen(),
                content:"../index/optPhoto",
                success:function (layero,index) {
                    var iframe = window["layui-layer-iframe" + index];
                    iframe.child("' . $val . '")
                }
            });
        });
        })
        </script>';
    }
}
if (!function_exists('rm')) {
    //清除缓存
    function rm(): void
    {
        delete_dir(root_path() . 'runtime');
    }
}

if (!function_exists('is_url')) {
    //是否
    function is_url($url)
    {
        if (preg_match("/^http(s)?:\\/\\/.+/", $url)) return $url;
    }
}

if (!function_exists('rand_string')) {
    /**
     *  随机数
     *
     * @param string     $length 长度
     * @param int|string $type   类型
     *
     * @return void
     */
    function rand_string(string $length = '32', int|string $type = 4): string
    {
        $rand = '';
        switch ($type) {
            case '1':
                $randstr = '0123456789';
                break;
            case '2':
                $randstr = 'abcdefghijklmnopqrstuvwxyz';
                break;
            case '3':
                $randstr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
                break;
            default:
                $randstr = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                break;
        }
        $max = strlen($randstr) - 1;
        mt_srand((double)microtime() * 1000000);
        for ($i = 0; $i < $length; $i++) {
            $rand .= $randstr[mt_rand(0, $max)];
        }
        return $rand;
    }
}

if (!function_exists('set_password')) {
    //密码截取
    function set_password($password): string
    {
        return substr(md5($password), 3, -3);
    }
}

/**
 * 数据签名认证
 */
function data_sign($data = []): string
{
    if (!is_array($data)) {
        $data = (array)$data;
    }
    ksort($data);
    $code = http_build_query($data);
    return sha1($code);
}

/* *
 * 修改网站配置文件
 * /
if (!function_exists('set_web'))
{
    function set_web($data = [])
    {
        $str = "<?php\r\n/**\r\n * 系统配置文件\r\n * /\r\nreturn [\r\n";
        foreach ($data as $key => $value) {
            if(is_array($value)){
            $str .= getArrTree($key,$value);
            }else{
                $str .= "\t'$key' => '$value',";
                $str .= "\r\n";
            }
        }
        $str .= '];';
        @file_put_contents(config_path().'web.php', $str);
    }
}
*/

if (!function_exists('get_arr_tree')) {
    /**
     * 递归配置数组
     */
    function get_arr_tree($key, $data, $level = "\t"): string
    {
        $i = "$level'$key' => [\r\n";
        foreach ($data as $k => $v) {
            if (is_array($v)) {
                $i .= get_arr_tree($k, $v, $level . "\t");
            } else {
                $i .= "$level\t'$k' => '$v',";
                $i .= "\r\n";
            }
        }
        return $i . "$level" . '],' . "\r\n";
    }
}

if (!function_exists('aes_encrypt')) {
    /**
     * @param string $string 需要加密的字符串
     * @param string $key    密钥
     *
     * @return string
     */
    function aes_encrypt(string $string, string $key = "ONSPEED"): string
    {
        $data = openssl_encrypt($string, 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
        return strtolower(bin2hex($data));
    }
}

if (!function_exists('aes_decrypt')) {
    /**
     * @param string $string 需要解密的字符串
     * @param string $key    密钥
     *
     * @return string
     */
    function aes_decrypt(string $string, string $key = "ONSPEED"): string
    {
        try {
            return openssl_decrypt(hex2bin($string), 'AES-128-ECB', $key, OPENSSL_RAW_DATA);
        } catch (\Exception $e) {
            return false;
        }
    }
}

if (!function_exists('get_field')) {
    /**
     * 获取指定表指定行指定字段
     *
     * @param string       $tn      完整表名
     * @param array|string $where   参数数组或者id值
     * @param string       $field   字段名,默认'name'
     * @param string       $default 获取失败的默认值,默认''
     * @param array        $order   排序数组
     *
     * @return string                获取到的内容
     */
    function get_field($tn, array|string $where, string $field = 'name', string $default = '', array $order = ['id' => 'desc']): string
    {
        if (!is_array($where)) {
            $where = ['id' => $where];
        }
        $row = \think\facade\Db::name($tn)->field([$field])->where($where)->order($order)->find();
        return $row === null ? $default : $row[$field];
    }
}

if (!function_exists('delete_dir')) {
    /**
     * 遍历删除文件夹所有内容
     *
     * @param string $dir 要删除的文件夹
     */
    function delete_dir($dir): void
    {
        $dh = opendir($dir);
        while ($file = readdir($dh)) {
            if ($file != '.' && $file != '..') {
                $filepath = $dir . '/' . $file;
                if (is_dir($filepath)) {
                    delete_dir($filepath);
                } else {
                    @unlink($filepath);
                }
            }
        }
        closedir($dh);
        @rmdir($dir);
    }
}

if (!function_exists('get_tree')) {
    /**
     * 递归无限级分类权限
     *
     * @param array  $data
     * @param int    $pid
     * @param string $field1 父级字段
     * @param string $field2 子级关联的父级字段
     * @param string $field3 子级键值
     *
     * @return array
     */
    function get_tree(array $data, int $pid = 0, string $field1 = 'id', string $field2 = 'pid', string $field3 = 'children'): array
    {
        $arr = [];
        foreach ($data as $k => $v) {
            if ($v[$field2] == $pid) {
                $v[$field3] = get_tree($data, $v[$field1]);
                $arr[]      = $v;
            }
        }
        return $arr;
    }
}

if (!function_exists('hump_underline')) {
    /**
     * 驼峰转下划线
     *
     * @param string $str 需要转换的字符串
     *
     * @return string      转换完毕的字符串
     */
    function hump_underline(string $str): string
    {
        return strtolower(trim(preg_replace('/[A-Z]/', '_\\0', $str), '_'));
    }
}

if (!function_exists('underline_hump')) {
    /**
     * 下划线转驼峰
     *
     * @param string $str 需要转换的字符串
     *
     * @return string      转换完毕的字符串
     */
    function underline_hump(string $str): string
    {
        return ucfirst(
            preg_replace_callback('/_([a-zA-Z])/', function ($match) {
                return strtoupper($match[1]);
            }, $str)
        );
    }
}

if (!function_exists('record_log')) {
    /**
     * @记录日志
     *
     * @param [type] $param
     * @param string $file
     *
     * @return void
     */
    function record_log($param, string $file = ''): void
    {
        $path = root_path() . 'log/' . $file . "/";
        if (!is_dir($path)) @mkdir($path, 0777, true);
        if (is_array($param)) {
            $param = json_encode($param, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
        }
        @file_put_contents(
            $path . date("Y_m_d", time()) . ".txt",
            "执行日期：" . "\r\n" . date('Y-m-d H:i:s', time()) . ' ' . "\n" . $param . "\r\n",
            FILE_APPEND
        );
    }
}



function fMakeMenu($rules, $type = 1, $setKeysById = null): array
{
    $retMenu = []; //返回值（也是顶层menu）
    $tmpMenu = []; //按id为key的menu
    foreach ($rules as $r) {
        if ($type === 1 && $r['type'] !== 1) { //api
            continue;
        }
        if ($r['show'] !== 1) { //是否显示
            continue;
        }

        //制作菜单：
        if (!isset($tmpMenu[$r['id']])) { //如果还不存在，则创建
            $tmpMenu[$r['id']] = ['type' => 1];
        }
        $tmpMenu[$r['id']]['id'] = $r['id'];
        $tmpMenu[$r['id']]['title'] = $r['name'];
        $tmpMenu[$r['id']]['icon'] = 'layui-icon ' . $r['icon'];
        $tmpMenu[$r['id']]['openType'] = "_iframe";
        $tmpMenu[$r['id']]['href'] = $r['menu_path'];

        //加入额外的keys
        if ($setKeysById) {
            //如果这个id在给定的Id列表内
            if (in_array($r['id'], $setKeysById[0])) {
                $tmpMenu[$r['id']][$setKeysById[1]] = $setKeysById[2]; //给特定key赋值
            }
        }

        if ($r['pid'] === 0) { //顶层
            $retMenu[] = &$tmpMenu[$r['id']];
            continue;
        }
        if (!isset($tmpMenu[$r['pid']])) { //子菜单
            $tmpMenu[$r['pid']] = ['children' => []]; //创建父菜单
        } elseif (!isset($tmpMenu[$r['pid']]['children'])) {
            $tmpMenu[$r['pid']]['children'] = [];
        }
        $tmpMenu[$r['pid']]['type'] = 0; //菜单
        $tmpMenu[$r['pid']]['children'][] = &$tmpMenu[$r['id']]; //加入父菜单 children
    }

    return $retMenu;
}



